﻿// --- Copyright (c) 2010 Steven Hartgers ---
// Copyright (C) 2010 Steven Hartgers All rights are reserved.
// Author contact: fiinix00/at\gmail.com
// ------------------------------------------------------------------------
// This program is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more detail
//  
// You should have received a copy of the GNU General Public License 
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel;

using Hack.Extensions;
using System.Diagnostics;
using Hack.Attributes;
using System.Data;
using System.Data.SqlClient;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Hack.Helpers
{
    public static class HelperViewer
    {
        public static IEnumerable<Type> GetHelperClasses()
        {
            return Hack.Helpers.ClassHelpers.GetAllClassesTYPE("Hack.Helpers")
                .Where(type => type.HasAttribute<Helper>() == true);
        }
    }

    [Helper]
    public static class ClassHelpers
    {
        /// <summary>
        /// Method to populate a list with all the class
        /// in the namespace provided by the user
        /// </summary>
        /// <param name="nameSpace">The namespace the user wants searched</param>
        /// <returns></returns>
        public static List<string> GetAllClassesSTRING(string nameSpace)
        {
            //create an Assembly and use its GetExecutingAssembly Method
            //http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.getexecutingassembly.aspx
            Assembly asm = Assembly.GetExecutingAssembly();
            //create a list for the namespaces
            List<string> namespaceList = new List<string>();
            //create a list that will hold all the classes
            //the suplied namespace is executing
            List<string> returnList = new List<string>();
            //loop through all the "Types" in the Assembly using
            //the GetType method:
            //http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.gettypes.aspx
            foreach (Type type in asm.GetTypes())
            {
                if (type.Namespace == nameSpace)
                    namespaceList.Add(type.Name);
            }
            //now loop through all the classes returned above and add
            //them to our classesName list
            foreach (String className in namespaceList)
                returnList.Add(className);
            //return the list
            return returnList;
        }
        public static IEnumerable<Type> GetAllClassesTYPE(string nameSpace)
        {
            Assembly asm = Assembly.GetExecutingAssembly();

            List<Type> ret = new List<Type>();

            foreach (Type type in asm.GetTypes())
            {
                if (type.Namespace == nameSpace)
                    ret.Add(type);
            }
            return ret;
        }
    }
    [Helper]
    public static class ProcessHelpers
    {
        public static Process FindProcess(IntPtr Handle)
        {
            foreach (Process process in
                System.Diagnostics.Process.GetProcesses().Where(
                    process =>
                    {
                        bool hasException = false;
                        try { IntPtr x = process.Handle; }
                        catch { hasException = true; }
                        return !hasException;
                    })
                )
            {
                if (process.Handle == Handle)
                    return process;

            }

            return null;
        }
        public static Process FindProcess(string title)
        {
            foreach (Process process in
    System.Diagnostics.Process.GetProcesses().Where(
        process =>
        {
            bool hasException = false;
            try { IntPtr x = process.Handle; }
            catch { hasException = true; }
            return !hasException;
        })
    )
            {
                if (process.MainWindowTitle == title)
                    return process;
            }
            return null;
        }
    }
    [Helper]
    public static class SpeedHelper
    {
        /// <summary>
        /// Notice: Each item runs 100 times, result time is x 100
        /// </summary>
        /// <param name="verusPlayer1"></param>
        /// <param name="verusPlayer2"></param>
        /// <returns></returns>
        public static string Versus(Action verusPlayer1, Action verusPlayer2)
        {
            long[] result = new long[2];

            Stopwatch sw = new Stopwatch();
            sw.Start();
            (100).Times(verusPlayer1);
            sw.Stop();
            result[0] += sw.ElapsedMilliseconds;

            sw.Reset(); // Reset and use again

            sw.Start();
            (100).Times(verusPlayer2);
            sw.Stop();
            result[1] += sw.ElapsedMilliseconds;

            if (result[0] < result[1])
            {
                return "VerusPlayer1 is faster: " + result[0] + ", VersusPlayer2 had: " + result[1];
            }
            else
            {
                return "VerusPlayer2 is faster: " + result[1] + ", VersusPlayer1 had: " + result[0];
            }
        }
    }
    [Helper]
    public static class ArrayHelper
    {
        /// <summary>
        /// Note: All indexes are null
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="rows"></param>
        /// <returns></returns>
        public static T[,] Generate2DArray<T>(int rows)
        {
            return new T[rows, rows];
        }
        public static T[, ,] Generate3DArray<T>(int rows)
        {
            return new T[rows, rows, rows];
        }
    }
    [Helper]
    public static class RandomHelper
    {
        private static Random randomSeed = new Random();

        /// <summary>
        /// Generates a random string with the given length
        /// </summary>
        /// <param name="size">Size of the string</param>
        /// <param name="lowerCase">If true, generate lowercase string</param>
        /// <returns>Random string</returns>
        public static string RandomString(int size, bool lowerCase)
        {
            // StringBuilder is faster than using strings (+=)
            StringBuilder RandStr = new StringBuilder(size);

            // Ascii start position (65 = A / 97 = a)
            int Start = (lowerCase) ? 97 : 65;

            // Add random chars
            for (int i = 0; i < size; i++)
                RandStr.Append((char)(26 * randomSeed.NextDouble() + Start));

            return RandStr.ToString();
        }

        /// <summary>
        /// Returns a random number.
        /// </summary>
        /// <param name="min">Minimal result</param>
        /// <param name="max">Maximal result</param>
        /// <returns>Random number</returns>
        public static int RandomNumber(int Minimal, int Maximal)
        {
            return randomSeed.Next(Minimal, Maximal);
        }

        /// <summary>
        /// Returns a random boolean value
        /// </summary>
        /// <returns>Random boolean value</returns>
        public static bool RandomBool()
        {
            return (randomSeed.NextDouble() > 0.5);
        }

        /// <summary>
        /// Returns a random color
        /// </summary>
        /// <returns></returns>
        public static System.Drawing.Color RandomColor()
        {
            return System.Drawing.Color.FromArgb(
                randomSeed.Next(256),
                randomSeed.Next(256),
                randomSeed.Next(256)
            );
        }

    }
    [Helper]
    public static class DataTableHelper
    {

        /// 
        /// Can stream DataTable to Browser, directly, you need to set 
        /// 
        /// Response.Clear();
        /// Response.Buffer= true;
        /// Response.ContentType = "application/vnd.ms-excel";
        /// Response.AddHeader("Content-Disposition", "inline;filename=Clientes.xls"); Response.Charset = "";
        /// this.EnableViewState = false
        /// // ACTUAL CODE 
        /// ProduceCSV(dt, Response.Output, true);
        /// 
        public static void ProduceCSV(DataTable dt, System.IO.TextWriter httpStream, bool WriteHeader)
        {
            if (WriteHeader)
            {
                string[] arr = new String[dt.Columns.Count];
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    arr[i] = dt.Columns[i].ColumnName;
                    arr[i] = GetWriteableValue(arr[i]);
                }

                httpStream.WriteLine(string.Join(",", arr));
            }

            for (int j = 0; j < dt.Rows.Count; j++)
            {
                string[] dataArr = new String[dt.Columns.Count];
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    object o = dt.Rows[j][i];
                    dataArr[i] = GetWriteableValue(o);
                }
                httpStream.WriteLine(string.Join(",", dataArr));
            }
        }

        #region CSV Producer
        public static void ProduceCSV(DataTable dt, System.IO.StreamWriter file, bool WriteHeader)
        {
            if (WriteHeader)
            {
                string[] arr = new String[dt.Columns.Count];
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    arr[i] = dt.Columns[i].ColumnName;
                    arr[i] = GetWriteableValue(arr[i]);
                }

                file.WriteLine(string.Join(",", arr));
            }

            for (int j = 0; j < dt.Rows.Count; j++)
            {
                string[] dataArr = new String[dt.Columns.Count];
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    object o = dt.Rows[j][i];
                    dataArr[i] = GetWriteableValue(o);
                }
                file.WriteLine(string.Join(",", dataArr));
            }
        }

        public static string GetWriteableValue(object o)
        {
            if (o == null || o == Convert.DBNull)
                return "";
            else if (o.ToString().IndexOf(",") == -1)
                return o.ToString();
            else
                return "\"" + o.ToString() + "\"";

        }
        #endregion
    }
    [Helper, OrginalAuthor(Url = "http://www.eggheadcafe.com/tutorials/aspnet/b3f8033a-ccfa-4e0b-a715-9a89c4e570e2/sql-helper-class-in-c.aspx")]
    public class SqlHelper
    {
        private string mstr_ConnectionString;
        private SqlConnection mobj_SqlConnection;
        private SqlCommand mobj_SqlCommand;
        private int mint_CommandTimeout = 30;

        public enum ExpectedType
        {

            StringType = 0,
            NumberType = 1,
            DateType = 2,
            BooleanType = 3,
            ImageType = 4
        }

        public SqlHelper(string ConnectionString)
        {
            try
            {

                mstr_ConnectionString = ConnectionString;

                mobj_SqlConnection = new SqlConnection(mstr_ConnectionString);
                mobj_SqlCommand = new SqlCommand();
                mobj_SqlCommand.CommandTimeout = mint_CommandTimeout;
                mobj_SqlCommand.Connection = mobj_SqlConnection;

                //ParseConnectionString();
            }
            catch (Exception ex)
            {
                throw new Exception("Error initializing data class." + Environment.NewLine + ex.Message);
            }
        }

        public void Dispose()
        {
            try
            {
                //Clean Up Connection Object
                if (mobj_SqlConnection != null)
                {
                    if (mobj_SqlConnection.State != ConnectionState.Closed)
                    {
                        mobj_SqlConnection.Close();
                    }
                    mobj_SqlConnection.Dispose();
                }

                //Clean Up Command Object
                if (mobj_SqlCommand != null)
                {
                    mobj_SqlCommand.Dispose();
                }

            }

            catch (Exception ex)
            {
                throw new Exception("Error disposing data class." + Environment.NewLine + ex.Message);
            }

        }

        public void CloseConnection()
        {
            if (mobj_SqlConnection.State != ConnectionState.Closed) mobj_SqlConnection.Close();
        }
        public int GetExecuteScalarByCommand(string Command)
        {

            object identity = 0;
            try
            {
                mobj_SqlCommand.CommandText = Command;
                mobj_SqlCommand.CommandTimeout = mint_CommandTimeout;
                mobj_SqlCommand.CommandType = CommandType.StoredProcedure;

                mobj_SqlConnection.Open();

                mobj_SqlCommand.Connection = mobj_SqlConnection;
                identity = mobj_SqlCommand.ExecuteScalar();
                CloseConnection();
            }
            catch (Exception ex)
            {
                CloseConnection();
                throw ex;
            }
            return Convert.ToInt32(identity);
        }

        public void GetExecuteNonQueryByCommand(string Command)
        {
            try
            {
                mobj_SqlCommand.CommandText = Command;
                mobj_SqlCommand.CommandTimeout = mint_CommandTimeout;
                mobj_SqlCommand.CommandType = CommandType.StoredProcedure;

                mobj_SqlConnection.Open();

                mobj_SqlCommand.Connection = mobj_SqlConnection;
                mobj_SqlCommand.ExecuteNonQuery();

                CloseConnection();
            }
            catch (Exception ex)
            {
                CloseConnection();
                throw ex;
            }
        }

        public DataSet GetDatasetByCommand(string Command)
        {
            try
            {
                mobj_SqlCommand.CommandText = Command;
                mobj_SqlCommand.CommandTimeout = mint_CommandTimeout;
                mobj_SqlCommand.CommandType = CommandType.StoredProcedure;

                mobj_SqlConnection.Open();

                SqlDataAdapter adpt = new SqlDataAdapter(mobj_SqlCommand);
                DataSet ds = new DataSet();
                adpt.Fill(ds);
                return ds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                CloseConnection();
            }
        }

        public SqlDataReader GetReaderBySQL(string strSQL)
        {
            mobj_SqlConnection.Open();
            try
            {
                SqlCommand myCommand = new SqlCommand(strSQL, mobj_SqlConnection);
                return myCommand.ExecuteReader();
            }
            catch (Exception ex)
            {
                CloseConnection();
                throw ex;
            }
        }

        public SqlDataReader GetReaderByCmd(string Command)
        {
            SqlDataReader objSqlDataReader = null;
            try
            {
                mobj_SqlCommand.CommandText = Command;
                mobj_SqlCommand.CommandType = CommandType.StoredProcedure;
                mobj_SqlCommand.CommandTimeout = mint_CommandTimeout;

                mobj_SqlConnection.Open();
                mobj_SqlCommand.Connection = mobj_SqlConnection;

                objSqlDataReader = mobj_SqlCommand.ExecuteReader();
                return objSqlDataReader;
            }
            catch (Exception ex)
            {
                CloseConnection();
                throw ex;
            }

        }

        public void AddParameterToSQLCommand(string ParameterName, SqlDbType ParameterType)
        {
            try
            {
                mobj_SqlCommand.Parameters.Add(new SqlParameter(ParameterName, ParameterType));
            }

            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void AddParameterToSQLCommand(string ParameterName, SqlDbType ParameterType, int ParameterSize)
        {
            try
            {
                mobj_SqlCommand.Parameters.Add(new SqlParameter(ParameterName, ParameterType, ParameterSize));
            }

            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void SetSQLCommandParameterValue(string ParameterName, object Value)
        {
            try
            {
                mobj_SqlCommand.Parameters[ParameterName].Value = Value;
            }

            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
    [Helper, OrginalAuthor(Url = "http://madskristensen.net/post/Serialization-helper-class-in-C-20.aspx")]
    public static class Serializer
    {
        /// <summary> 
        /// The type of serialization. 
        /// </summary> 
        public enum SerializeMode
        {
            /// <summary>Will serialize to a binary format.</summary> 
            Binary,
            /// <summary>Will serialize to an XML format.</summary> 
            Xml
        }
        private static object _Lock = new object();

        #region Serialize

        /// <summary> 
        /// Serialize an object and store it in a file. 
        /// </summary> 
        /// <param name="mode">The instance of an object to serialize</param> 
        /// <param name="instance">The instance of an object to serialize.</param> 
        /// <param name="filePath">The location on disk.</param> 
        /// <returns>A serialized MemoryStream.</returns> 
        public static void Serialize(SerializeMode mode, object instance, string filePath)
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                MemoryStream stream = Serialize(mode, instance);
                byte[] buffer = stream.ToArray();
                fs.Write(buffer, 0, buffer.Length);
                fs.Flush();
            }
        }

        /// <summary> 
        /// Serializes any instances of any objects. 
        /// </summary> 
        /// <param name="mode">The instance of an object to serialize</param> 
        /// <param name="instance">The instance of an object to serialize.</param> 
        /// <returns>A serialized MemoryStream.</returns> 
        public static MemoryStream Serialize(SerializeMode mode, object instance)
        {
            if (instance == null)
                throw new ArgumentNullException("The instance object is null.");

            lock (_Lock)
            {
                MemoryStream stream = new MemoryStream();
                switch (mode)
                {
                    case SerializeMode.Xml:
                        SerializeXml(ref stream, ref instance);
                        return stream;

                    default:
                        SerializeBinary(ref stream, ref instance);
                        return stream;
                }
            }
        }

        private static void SerializeBinary(ref MemoryStream stream, ref object instance)
        {
            BinaryFormatter bfor = new BinaryFormatter();
            bfor.Serialize(stream, instance);
            bfor = null;
        }

        private static void SerializeXml(ref MemoryStream stream, ref object instance)
        {
            XmlSerializer ser = new XmlSerializer(instance.GetType());
            XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
            xsn.Add(string.Empty, null);
            ser.Serialize(stream, instance, xsn);
            ser = null;
        }

        #endregion

        #region Deserialize

        /// <summary> 
        /// Deserialize an object from a byte array 
        /// </summary> 
        /// <param name="mode">The mode to deserialize the object.</param> 
        /// <param name="instance">Specify an instance of an object to deserialize.</param> 
        /// <param name="buffer">A byte array containing the serialized object, that needs 
        /// to be deserialized</param> 
        /// <returns>A deserialized object.</returns> 
        public static T Deserialize<T>(SerializeMode mode, T instance, byte[] buffer)
        {
            if (buffer == null)
                throw new ArgumentNullException("The byte array is null.");

            lock (_Lock)
            {
                switch (mode)
                {
                    case SerializeMode.Xml:
                        return DeserializeXml<T>(instance, buffer);

                    default:
                        return DeserializeBinary<T>(instance, buffer);
                }
            }
        }

        /// <summary> 
        /// Deserialize an object from a location on disk or network. 
        /// </summary> 
        /// <param name="mode">The mode to deserialize the object.</param> 
        /// <param name="instance">Specify an instance of an object to deserialize.</param> 
        /// <param name="filePath">The path to the serialized object.</param> 
        /// <returns>A deserialized object.</returns> 
        public static T Deserialize<T>(SerializeMode mode, T instance, string filePath)
        {
            byte[] buffer = null;

            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    buffer = new byte[fs.Length];
                    fs.Read(buffer, 0, buffer.Length);
                    return Deserialize<T>(mode, instance, buffer);
                }
            }
            finally
            {
                buffer = null;
            }
        }

        /// <summary> 
        /// Deserializes an object from a byte array 
        /// </summary> 
        private static T DeserializeXml<T>(T instance, byte[] buffer)
        {
            using (MemoryStream stream = new MemoryStream(buffer))
            {
                XmlSerializer ser = new XmlSerializer(typeof(T));
                instance = (T)ser.Deserialize(stream);
                return instance;
            }
        }

        /// <summary> 
        /// Deserializes the object from a byte array. 
        /// </summary> 
        /// <param name="instance">Specify an instance of an object to deserialize.</param> 
        /// <param name="array">A serialized byte array</param> 
        private static T DeserializeBinary<T>(T instance, byte[] array)
        {
            BinaryFormatter bf;
            MemoryStream ms = null;
            try
            {
                ms = new MemoryStream(array);
                {
                    bf = new BinaryFormatter();
                    instance = (T)bf.Deserialize(ms);
                    return instance;
                }
            }
            finally
            {
                bf = null;
                if (ms != null) ms.Close();
                ms = null;
            }
        }

        #endregion

    }
}